package pathFinder.bfs;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Vector;

import pathFinder.utils.Logger;


public class BFS {
	/**
	 * visitedList The list of Nodes not already visited.
	 */
	private ArrayList<Node> visitedList;
	/**
	 *  edgeList list of flights for current request
	 */
	private ArrayList<Edge> edgeList;
	// to be able to catch the next flight
	private float forcedDelay = 0;
	Logger log;
	/**
	 *  paths lists of viable paths form start to destination
	 */
	private ArrayList<Path> paths;
	private int maxFlights = 10;
	public BFS() {
		visitedList = new ArrayList<Node>();
		paths = new ArrayList<>();
		log = new Logger();
		edgeList = new ArrayList<>();
	}
	

	private void bfs(Node node, int depth){
		
		//System.out.println(depth);
		if(depth == 0)
			return;
		
		// if reached destination construct path and add save it
		
		//System.out.println(node.name);
		if(node.isGoal()) 
			paths.add(new Path((ArrayList<Edge>)edgeList.clone()));

		visitedList.add(node);
		Edge lastFlight = edgeList.get(edgeList.size()-1);
		
		float arrivalHour = lastFlight.getHourDeparture()+lastFlight.getDurationFlight();
		//go through all the current Nodes neighbors and calculate if one should be our next step

		for(Edge edge : node.connectionList) {
			Node neighbor = edge.getDestination();
		
			if(arrivalHour + forcedDelay< edge.getHourDeparture()){
				edgeList.add(edge);
				// verify if available flight edge
				if(!visitedList.contains(neighbor)){
					bfs(neighbor,depth-1);
				}
				edgeList.remove(edgeList.size()-1);
			}
		}		
		visitedList.remove(node);
		
	}
	public ArrayList<Path> calcAllPaths(Graph graph,String startAirport, String destAirport,int maxFlights2) {

		this.maxFlights  = maxFlights2;
		//System.out.println(maxFlights2);
		Node startNode = graph.getAirpotNode(startAirport);
		Node destinationNode = graph.getAirpotNode(destAirport);
		startNode.setStart(true);
		destinationNode.setGoal(true);
		
		
		// check if our current location is the current destination
		if(startNode.isGoal()) {
			return null;
		}
		visitedList.clear();
		visitedList.add(startNode);
		edgeList.clear();
		//System.out.println(startNode.name+startNode.connectionList.size());
		int departureHour = 0;
		for(Edge edge : startNode.connectionList) {
					Node neighbor = edge.getDestination();
					// select next available flight - flighs after 
					if(departureHour + forcedDelay< edge.getHourDeparture()){
						edgeList.add(edge);
						//System.out.println(neighbor.name+neighbor.connectionList.size());
							// avoid looping through flights
							if(!visitedList.contains(neighbor)){
								//System.out.println(maxFlights);
								bfs(neighbor,maxFlights);
								//System.out.println(maxFlights+neighbor.name+neighbor.connectionList.size());
								
							}
						
						edgeList.remove(edgeList.size()-1);
					}
		}

		return paths;
	}
/*
	private ArrayList<String> reconstructPath(Node node) {
		ArrayList<String> path = new ArrayList<String>();
			
		while(!(node.getPreviousNode() == null)) {
			path.add(0, node.name);
			node = node.getPreviousNode();
			
		}
		return null;
	}

	private class SortedNodeList {

		private ArrayList<Node> list = new ArrayList<Node>();

		public Node getFirst() {
			return list.get(0);
		}

		public void clear() {
			list.clear();
		}

		public void add(Node node) {
			list.add(node);
			Collections.sort(list);
		}

		public void remove(Node n) {
			list.remove(n);
		}

		public int size() {
			return list.size();
		}

		public boolean contains(Node n) {
			return list.contains(n);
		}
	}
*/
}
